package com.rq.viewtestapplication.manager;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;

import com.rq.viewtestapplication.LOG;

import java.util.HashMap;

import static com.rq.viewtestapplication.manager.TouchManagerManager.Action.*;


public class TouchManagerManager {


    enum Action {
        NONE, MOVE_ITEM, MOVE_CANVAS, ZOOM_CANVAS, ZOOM_ITEM
    }

    private static final long PRESS_CHANGE_TIME = (long) (ViewConfiguration.getLongPressTimeout() * 1.5);
    private ChildManager childManager;

    public void attachManager(ChildManager childManager, LinkManager linkManager) {
        this.childManager = childManager;
    }

    boolean isTouchItem = false;
    ViewGroup touchView = null;

    public boolean isTouchItem() {
        return isTouchItem;
    }

    public boolean dispatchTouchEvent(MotionEvent ev) {
        View focusView = childManager.getFirstFocusView(ev);
        if (focusView instanceof ViewGroup && ((ViewGroup) focusView).onInterceptTouchEvent(ev)) {
            this.isTouchItem = true;
            focusView.onTouchEvent(ev);
            return true;
        }
        this.isTouchItem = false;
        return false;
    }

    public boolean move2Item(MotionEvent ev) {
        return this.touchView.onTouchEvent(ev);
    }

    private Action actionTag = NONE;//动作种类 0-无动作  1-移动子项 3-缩放画布
    private float newDistance = 1, oldDistance = 1, scale = 1, newCenterX = 0, newCenterY = 0;
    private float downX, downY;
    private long focusItemDown = 0;
    private VelocityTracker mVelocityTracker = VelocityTracker.obtain();

    private void reset() {
        actionTag = NONE;
        newDistance = 1;
        oldDistance = 1;
        scale = 1;
        newCenterX = 0;
        newCenterY = 0;
        downX = 0;
        downY = 0;
        focusItemDown = 0;
        childManager.checkThenReset();
    }

    public Action getActionTag() {
        return actionTag;
    }

    public boolean dealTouch(MotionEvent ev) {
        LOG.e("TouchManagerManager", ev.getActionMasked() + ">>dealTouch:" + ev.getX() + "," + ev.getY());
        float x = ev.getX();
        float y = ev.getY();
        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                downX = x;
                downY = y;
                if (childManager.isZoomItem(x, y)) {
                    actionTag = ZOOM_ITEM;
                    mVelocityTracker = VelocityTracker.obtain();
                    mVelocityTracker.clear();
                    mVelocityTracker.addMovement(ev);
                } else if (childManager.getFocusIndexInView(x, y) > -1) {
                    actionTag = MOVE_ITEM;
                    focusItemDown = System.currentTimeMillis();
                    mVelocityTracker = VelocityTracker.obtain();
                    mVelocityTracker.clear();
                    mVelocityTracker.addMovement(ev);
                } else {
                    actionTag = MOVE_CANVAS;
                }
                return true;
            case MotionEvent.ACTION_POINTER_DOWN:
                if (ev.getPointerCount() == 2) {//getPointerCount返回的是手指的数量
                    oldDistance = calculateDistance(ev);//计算距离
                    newCenterX = calculateCenter(ev, true);
                    newCenterY = calculateCenter(ev, false);
                }
                actionTag = ZOOM_CANVAS;
                return true;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (isTouchItem()) {
                    return move2Item(ev);
                }
                if (checkIsClick(ev)) {
                    dealClick(ev);
                    childManager.reset();
                    return true;
                } else if (actionTag == ZOOM_ITEM) {
                    childManager.updateFocus();
                    mVelocityTracker.recycle();
                } else if (actionTag == MOVE_ITEM) {
                    childManager.updateFocus();
                    mVelocityTracker.recycle();
                } else if (actionTag == MOVE_CANVAS) {
                    childManager.updateAll();
                } else if (actionTag == ZOOM_CANVAS) {
                    childManager.updateAll();
                }
                childManager.reset();
                actionTag = NONE;
                reset();
                return true;
            case MotionEvent.ACTION_MOVE:
                if (isTouchItem()) {
                    LOG.e("TouchManagerManager", "131:");
                    return move2Item(ev);
                }
                if (actionTag == ZOOM_CANVAS && ev.getPointerCount() == 2) {
                    newDistance = calculateDistance(ev);
                    scale = newDistance / oldDistance;
                    childManager.zoomAll(newCenterX, newCenterY, scale);
                } else if (actionTag == MOVE_CANVAS) {
                    childManager.moveAll(x - downX, y - downY);
                } else if (actionTag == ZOOM_ITEM) {
                    mVelocityTracker = VelocityTracker.obtain();
                    mVelocityTracker.clear();
                    mVelocityTracker.addMovement(ev);
                    mVelocityTracker.computeCurrentVelocity(1000);
                    childManager.zoomItem(x, y, mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
                } else {
                    if (Math.abs(x - downX) + Math.abs(y - downY) < 10) {
                        if (System.currentTimeMillis() - focusItemDown > 800) {
                            focusItemDown = System.currentTimeMillis();
                            childManager.getEventInViewOtherIndex(x, y);
                            return true;
                        }
                    } else if (actionTag == MOVE_ITEM) {
                        mVelocityTracker.addMovement(ev);
                        mVelocityTracker.computeCurrentVelocity(1000);
                        childManager.moveFocus(x - downX, y - downY, mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
                        return true;
                    }
                }
                break;
        }
        return false;
    }

    SparseArray<Long> clickTime = new SparseArray<>();
    public static final int DOUBLE_CLICK_DURATION_TIME = 200;

    private void dealClick(MotionEvent ev) {
        final View view = childManager.getFirstFocusView(ev);
        long lastClickTime = clickTime.get(view.hashCode(), 0L);
        if (lastClickTime > 0) {
            if (System.currentTimeMillis() - lastClickTime < DOUBLE_CLICK_DURATION_TIME) {
                LOG.e("TouchManagerManager", view.getTag() + ":双击事件");
                clickTime.remove(view.hashCode());
                if(view instanceof OnDoubleClickListener){
                    ((OnDoubleClickListener)view).performDoubleClick();
                }
            }
        } else {
            clickTime.put(view.hashCode(), System.currentTimeMillis());
            view.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (clickTime.get(view.hashCode(), 0L) > 0) {
                        LOG.e("TouchManagerManager", view.getTag() + ":单击事件");
                        clickTime.remove(view.hashCode());
                        view.performClick();
                    }
                }
            }, DOUBLE_CLICK_DURATION_TIME);
        }
    }

    public void drawForeground(Canvas canvas, Paint focusPaint) {
        RectF focusF = childManager.getFocusRect();
        if (focusF != null) {
            canvas.drawRect(focusF, focusPaint);
        }
    }

    private boolean checkIsClick(MotionEvent ev) {
        return Math.abs(ev.getX() - downX) + Math.abs(ev.getY() - downY) < 10 && System.currentTimeMillis() - focusItemDown < PRESS_CHANGE_TIME;
    }

    private float calculateDistance(MotionEvent ev) {
        float x1 = ev.getX(0);//第一个点x坐标
        float y1 = ev.getY(0);//第一个点y坐标
        if (ev.getPointerCount() == 1) return 1;
        float x2 = ev.getX(1);//第二个点x坐标
        float y2 = ev.getY(1);//第二个点y坐标
        return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));

    }

    private float calculateCenter(MotionEvent ev, boolean isX) {
        return isX ? (ev.getX(1) + ev.getX(0)) / 2 : (ev.getY(1) + ev.getY(0)) / 2;
    }
}
